package com.google.code.p.restrpc.client.cluster;

import java.util.List;

import com.google.code.p.restrpc.RpcContext;
import com.google.code.p.restrpc.RpcException;
import com.google.code.p.restrpc.RpcRequest;
import com.google.code.p.restrpc.RpcResponse;
import com.google.code.p.restrpc.client.RpcProxy;
import com.google.code.p.restrpc.client.cache.ServiceMetadataRepository;
import com.google.code.p.restrpc.client.proxy.RpcProxyMetadata;
import com.google.code.p.restrpc.directory.RemoteServiceDefinition;
import com.google.code.p.restrpc.directory.RemoteServiceDefinitionVisitor;

/**
 * @author dz
 */
public abstract class AbstractFailureRecoveryStrategy implements
                                                     FailureRecoveryStrategy {
    
    /**
     * @param context
     * @param requests
     * @return
     * @throws RpcException
     */
    public RpcResponse invoke(ClusteredRpcContext context,
                              List<RpcRequest> requests) throws RpcException {
        throw new UnsupportedOperationException();
    }
    
    /**
     * @param context
     * @param rpcRequest
     */
    protected void disableRemoteServiceDefinition(ClusteredRpcContext context,
                                                  final RpcRequest rpcRequest) {
        disableRemoteServiceDefinition(context.getRpcContext(), rpcRequest);
    }
    
    /**
     * @param context
     * @param rpcRequest
     */
    protected void disableRemoteServiceDefinition(RpcContext context,
                                                  final RpcRequest rpcRequest) {
        RpcProxy rpcProxy = context.getRpcProxy();
        if (rpcProxy instanceof RpcProxyMetadata) {
            RpcProxyMetadata rpcProxyMetadata = (RpcProxyMetadata) rpcProxy;
            ServiceMetadataRepository serviceMetadataRepository = rpcProxyMetadata.getServiceMetadataRepository();
            if (serviceMetadataRepository != null) {
                serviceMetadataRepository.accept(rpcRequest.getServiceName(),
                                                 new RemoteServiceDefinitionVisitor() {
                                                     
                                                     public void visit(RemoteServiceDefinition remoteServiceDefinition) {
                                                         if (remoteServiceDefinition.matches(rpcRequest.getServiceName(),
                                                                                             rpcRequest.getAddress(),
                                                                                             rpcRequest.getPort())) {
                                                             remoteServiceDefinition.disable();
                                                         }
                                                     }
                                                 });
            }
        }
    }
    
}
